/*
 * Copyright (C) Cvitek Co., Ltd. 2019-2020. All rights reserved.
 *
 * File Name: include/cvi_unf_cipher.h
 * Description:
 */

#ifndef CVI_UNF_CIPHER_H_FYUVBDPZ
#define CVI_UNF_CIPHER_H_FYUVBDPZ

#include <cvi_type.h>
#include <cvi_sys.h>

#define CVI_ERR_CIPHER_NOT_INIT -0x0001
#define CVI_ERR_CIPHER_INVALID_HANDLE -0x0002
#define CVI_ERR_CIPHER_INVALID_POINT -0x0003
#define CVI_ERR_CIPHER_INVALID_PARA -0x0004
#define CVI_ERR_CIPHER_FAILED_INIT -0x0005
#define CVI_ERR_CIPHER_FAILED_GETHANDLE -0x0006
#define CVI_ERR_CIPHER_FAILED_RELEASEHANDLE -0x0007
#define CVI_ERR_CIPHER_BUSY -0x0008
#define CVI_ERR_CIPHER_TIMEOUT -0x0009
#define CVI_ERR_CIPHER_UNSUPPORTED -0x000A

#define CVI_CIPHER_HANDLE uintptr_t

#define CIPHER_IV_CHANGE_ONE_PKG (1)
#define CIPHER_IV_CHANGE_ALL_PKG (2)

typedef enum {
	CVI_UNF_CIPHER_WORK_MODE_ECB,
	CVI_UNF_CIPHER_WORK_MODE_CBC,
	CVI_UNF_CIPHER_WORK_MODE_CFB,
	CVI_UNF_CIPHER_WORK_MODE_OFB,
	CVI_UNF_CIPHER_WORK_MODE_CTR,
	CVI_UNF_CIPHER_WORK_MODE_CCM,
	CVI_UNF_CIPHER_WORK_MODE_GCM,
	CVI_UNF_CIPHER_WORK_MODE_CBC_CTS,
	CVI_UNF_CIPHER_WORK_MODE_BUTT,
	CVI_UNF_CIPHER_WORK_MODE_INVALID = -1,
} CVI_UNF_CIPHER_WORK_MODE_E;

typedef enum {
	CVI_UNF_CIPHER_ALG_DES = 0x0,
	CVI_UNF_CIPHER_ALG_3DES = 0x1,
	CVI_UNF_CIPHER_ALG_AES = 0x2,
	CVI_UNF_CIPHER_ALG_SM1 = 0x3,
	CVI_UNF_CIPHER_ALG_SM4 = 0x4,
	CVI_UNF_CIPHER_ALG_DMA = 0x5,
	CVI_UNF_CIPHER_ALG_BUTT = 0x6,
	CVI_UNF_CIPHER_ALG_INVALID = -1,
} CVI_UNF_CIPHER_ALG_E;

typedef enum {
	CVI_UNF_CIPHER_KEY_AES_128BIT = 0x0,
	CVI_UNF_CIPHER_KEY_AES_192BIT = 0x1,
	CVI_UNF_CIPHER_KEY_AES_256BIT = 0x2,
	CVI_UNF_CIPHER_KEY_DES_3KEY = 0x2,
	CVI_UNF_CIPHER_KEY_DES_2KEY = 0x3,
	CVI_UNF_CIPHER_KEY_DEFAULT = 0x0,
	CVI_UNF_CIPHER_KEY_INVALID = -1,
} CVI_UNF_CIPHER_KEY_LENGTH_E;

typedef enum {
	CVI_UNF_CIPHER_BIT_WIDTH_64BIT = 0x0,
	CVI_UNF_CIPHER_BIT_WIDTH_8BIT = 0x1,
	CVI_UNF_CIPHER_BIT_WIDTH_1BIT = 0x2,
	CVI_UNF_CIPHER_BIT_WIDTH_128BIT = 0x3,
	CVI_UNF_CIPHER_BIT_WIDTH_INVALID = -1,
} CVI_UNF_CIPHER_BIT_WIDTH_E;

typedef struct {
	CVI_U32 bit1IV : 2;
	CVI_U32 bitsResv : 30;
} CVI_UNF_CIPHER_CTRL_CHANGE_FLAG_S;

typedef enum {
	CVI_UNF_CIPHER_TYPE_NORMAL = 0x0,
	CVI_UNF_CIPHER_TYPE_COPY_AVOID,
	CVI_UNF_CIPHER_TYPE_BUTT,
	CVI_UNF_CIPHER_TYPE_INVALID = -1,
} CVI_UNF_CIPHER_TYPE_E;

typedef struct {
	CVI_UNF_CIPHER_TYPE_E enCipherType;
} CVI_UNF_CIPHER_ATTS_S;

typedef enum {
	CVI_UNF_CIPHER_SM1_ROUND_08 = 0x00,
	CVI_UNF_CIPHER_SM1_ROUND_10 = 0x01,
	CVI_UNF_CIPHER_SM1_ROUND_12 = 0x02,
	CVI_UNF_CIPHER_SM1_ROUND_14 = 0x03,
	CVI_UNF_CIPHER_SM1_ROUND_BUTT,
	CVI_UNF_CIPHER_SM1_ROUND_INVALID = -1,
} CVI_UNF_CIPHER_SM1_ROUND_E;

typedef struct {
	CVI_U32 u32Key[8];
	CVI_U32 u32IV[4];
	CVI_UNF_CIPHER_ALG_E enAlg;
	CVI_UNF_CIPHER_BIT_WIDTH_E enBitWidth;
	CVI_UNF_CIPHER_WORK_MODE_E enWorkMode;
	CVI_UNF_CIPHER_KEY_LENGTH_E enKeyLen;
	CVI_UNF_CIPHER_CTRL_CHANGE_FLAG_S stChangeFlags;
} CVI_UNF_CIPHER_CTRL_S;

typedef struct {
	CVI_U32 u32EvenKey[8];
	CVI_U32 u32OddKey[8];
	CVI_U32 u32IV[4];
	CVI_UNF_CIPHER_BIT_WIDTH_E enBitWidth;
	CVI_UNF_CIPHER_KEY_LENGTH_E enKeyLen;
	CVI_UNF_CIPHER_CTRL_CHANGE_FLAG_S stChangeFlags;
} CVI_UNF_CIPHER_CTRL_AES_S;

typedef struct {
	CVI_U32 u32Key[8];
	CVI_U32 u32IV[4];
	CVI_UNF_CIPHER_KEY_LENGTH_E enKeyLen;
	CVI_U32 u32IVLen;
	CVI_U32 u32TagLen;
	CVI_U32 u32ALen;
	CVI_SIZE_T szAdataAddr;
} CVI_UNF_CIPHER_CTRL_AES_CCM_GCM_S;

typedef struct {
	CVI_U32 u32Key[2];
	CVI_U32 u32IV[2];
	CVI_UNF_CIPHER_BIT_WIDTH_E enBitWidth;
	CVI_UNF_CIPHER_CTRL_CHANGE_FLAG_S stChangeFlags;
} CVI_UNF_CIPHER_CTRL_DES_S;

typedef struct {
	CVI_U32 u32Key[6];
	CVI_U32 u32IV[2];
	CVI_UNF_CIPHER_BIT_WIDTH_E enBitWidth;
	CVI_UNF_CIPHER_KEY_LENGTH_E enKeyLen;
	CVI_UNF_CIPHER_CTRL_CHANGE_FLAG_S stChangeFlags;
} CVI_UNF_CIPHER_CTRL_3DES_S;

typedef struct {
	CVI_U32 u32EK[4];
	CVI_U32 u32AK[4];
	CVI_U32 u32SK[4];
	CVI_U32 u32IV[4];
	CVI_UNF_CIPHER_BIT_WIDTH_E enBitWidth;
	CVI_UNF_CIPHER_SM1_ROUND_E enSm1Round;
	CVI_UNF_CIPHER_CTRL_CHANGE_FLAG_S stChangeFlags;
} CVI_UNF_CIPHER_CTRL_SM1_S;

typedef struct {
	CVI_U32 u32Key[4];
	CVI_U32 u32IV[4];
	CVI_UNF_CIPHER_CTRL_CHANGE_FLAG_S stChangeFlags;
} CVI_UNF_CIPHER_CTRL_SM4_S;

typedef struct {
	CVI_UNF_CIPHER_ALG_E enAlg;
	CVI_UNF_CIPHER_WORK_MODE_E enWorkMode;

	CVI_VOID *pParam;
} CVI_UNF_CIPHER_CTRL_EX_S;

typedef struct {
	CVI_SIZE_T szSrcAddr;
	CVI_SIZE_T szDestAddr;
	CVI_U32 u32ByteLength;
	CVI_BOOL bOddKey;
} CVI_UNF_CIPHER_DATA_S;

typedef enum {
	CVI_UNF_CIPHER_HASH_TYPE_SHA1,
	CVI_UNF_CIPHER_HASH_TYPE_SHA224,
	CVI_UNF_CIPHER_HASH_TYPE_SHA256,
	CVI_UNF_CIPHER_HASH_TYPE_SHA384,
	CVI_UNF_CIPHER_HASH_TYPE_SHA512,
	CVI_UNF_CIPHER_HASH_TYPE_HMAC_SHA1,
	CVI_UNF_CIPHER_HASH_TYPE_HMAC_SHA224,
	CVI_UNF_CIPHER_HASH_TYPE_HMAC_SHA256,
	CVI_UNF_CIPHER_HASH_TYPE_HMAC_SHA384,
	CVI_UNF_CIPHER_HASH_TYPE_HMAC_SHA512,
	CVI_UNF_CIPHER_HASH_TYPE_SM3,
	CVI_UNF_CIPHER_HASH_TYPE_BUTT,
	CVI_UNF_CIPHER_HASH_TYPE_INVALID = -1,
} CVI_UNF_CIPHER_HASH_TYPE_E;

typedef struct {
	CVI_U8 *pu8HMACKey;
	CVI_U32 u32HMACKeyLen;
	CVI_UNF_CIPHER_HASH_TYPE_E eShaType;
} CVI_UNF_CIPHER_HASH_ATTS_S;

typedef enum {
	CVI_UNF_CIPHER_RSA_ENC_SCHEME_NO_PADDING,
	CVI_UNF_CIPHER_RSA_ENC_SCHEME_BLOCK_TYPE_0,
	CVI_UNF_CIPHER_RSA_ENC_SCHEME_BLOCK_TYPE_1,
	CVI_UNF_CIPHER_RSA_ENC_SCHEME_BLOCK_TYPE_2,
	CVI_UNF_CIPHER_RSA_ENC_SCHEME_RSAES_OAEP_SHA1,
	CVI_UNF_CIPHER_RSA_ENC_SCHEME_RSAES_OAEP_SHA224,
	CVI_UNF_CIPHER_RSA_ENC_SCHEME_RSAES_OAEP_SHA256,
	CVI_UNF_CIPHER_RSA_ENC_SCHEME_RSAES_OAEP_SHA384,
	CVI_UNF_CIPHER_RSA_ENC_SCHEME_RSAES_OAEP_SHA512,
	CVI_UNF_CIPHER_RSA_ENC_SCHEME_RSAES_PKCS1_V1_5,
	CVI_UNF_CIPHER_RSA_ENC_SCHEME_BUTT,
	CVI_UNF_CIPHER_RSA_ENC_SCHEME_INVALID = -1,
} CVI_UNF_CIPHER_RSA_ENC_SCHEME_E;

typedef enum {
	CVI_UNF_CIPHER_RSA_SIGN_SCHEME_RSASSA_PKCS1_V15_SHA1 = 0x100,
	CVI_UNF_CIPHER_RSA_SIGN_SCHEME_RSASSA_PKCS1_V15_SHA224,
	CVI_UNF_CIPHER_RSA_SIGN_SCHEME_RSASSA_PKCS1_V15_SHA256,
	CVI_UNF_CIPHER_RSA_SIGN_SCHEME_RSASSA_PKCS1_V15_SHA384,
	CVI_UNF_CIPHER_RSA_SIGN_SCHEME_RSASSA_PKCS1_V15_SHA512,
	CVI_UNF_CIPHER_RSA_SIGN_SCHEME_RSASSA_PKCS1_PSS_SHA1,
	CVI_UNF_CIPHER_RSA_SIGN_SCHEME_RSASSA_PKCS1_PSS_SHA224,
	CVI_UNF_CIPHER_RSA_SIGN_SCHEME_RSASSA_PKCS1_PSS_SHA256,
	CVI_UNF_CIPHER_RSA_SIGN_SCHEME_RSASSA_PKCS1_PSS_SHA384,
	CVI_UNF_CIPHER_RSA_SIGN_SCHEME_RSASSA_PKCS1_PSS_SHA512,
	CVI_UNF_CIPHER_RSA_SIGN_SCHEME_BUTT,
	CVI_UNF_CIPHER_RSA_SIGN_SCHEME_INVALID = -1,
} CVI_UNF_CIPHER_RSA_SIGN_SCHEME_E;

typedef struct {
	CVI_U8 *pu8N;
	CVI_U8 *pu8E;
	CVI_U16 u16NLen;
	CVI_U16 u16ELen;
} CVI_UNF_CIPHER_RSA_PUB_KEY_S;

typedef struct {
	CVI_U8 *pu8N;
	CVI_U8 *pu8E;
	CVI_U8 *pu8D;
	CVI_U8 *pu8P;
	CVI_U8 *pu8Q;
	CVI_U8 *pu8DP;
	CVI_U8 *pu8DQ;
	CVI_U8 *pu8QP;
	CVI_U16 u16NLen;
	CVI_U16 u16ELen;
	CVI_U16 u16DLen;
	CVI_U16 u16PLen;
	CVI_U16 u16QLen;
	CVI_U16 u16DPLen;
	CVI_U16 u16DQLen;
	CVI_U16 u16QPLen;
} CVI_UNF_CIPHER_RSA_PRI_KEY_S;

typedef struct {
	CVI_UNF_CIPHER_RSA_ENC_SCHEME_E enScheme;
	CVI_UNF_CIPHER_RSA_PUB_KEY_S stPubKey;
} CVI_UNF_CIPHER_RSA_PUB_ENC_S;

typedef struct {
	CVI_UNF_CIPHER_RSA_ENC_SCHEME_E enScheme;
	CVI_UNF_CIPHER_RSA_PRI_KEY_S stPriKey;
} CVI_UNF_CIPHER_RSA_PRI_ENC_S;

typedef struct {
	CVI_UNF_CIPHER_RSA_SIGN_SCHEME_E enScheme;
	CVI_UNF_CIPHER_RSA_PRI_KEY_S stPriKey;
} CVI_UNF_CIPHER_RSA_SIGN_S;

typedef struct {
	CVI_UNF_CIPHER_RSA_SIGN_SCHEME_E enScheme;
	CVI_UNF_CIPHER_RSA_PUB_KEY_S stPubKey;
} CVI_UNF_CIPHER_RSA_VERIFY_S;

/** <!-- ==== Structure Definition End ==== */

#define CVI_UNF_CIPHER_Open CVI_UNF_CIPHER_Init
#define CVI_UNF_CIPHER_Close CVI_UNF_CIPHER_DeInit

/** <!-- [CIPHER] */

CVI_S32 CVI_UNF_CIPHER_Init(void);

CVI_S32 CVI_UNF_CIPHER_DeInit(void);

CVI_S32 CVI_UNF_CIPHER_CreateHandle(CVI_CIPHER_HANDLE *phCipher, const CVI_UNF_CIPHER_ATTS_S *pstCipherAttr);

CVI_S32 CVI_UNF_CIPHER_DestroyHandle(CVI_CIPHER_HANDLE hCipher);

CVI_S32 CVI_UNF_CIPHER_ConfigHandle(CVI_CIPHER_HANDLE hCipher, const CVI_UNF_CIPHER_CTRL_S *pstCtrl);

CVI_S32 CVI_UNF_CIPHER_ConfigHandleEx(CVI_CIPHER_HANDLE hCipher, const CVI_UNF_CIPHER_CTRL_EX_S *pstExCtrl);

CVI_S32 CVI_UNF_CIPHER_Encrypt(CVI_CIPHER_HANDLE hCipher, CVI_SIZE_T szSrcAddr, CVI_SIZE_T szDestAddr,
			       CVI_U32 u32ByteLength);

CVI_S32 CVI_UNF_CIPHER_Decrypt(CVI_CIPHER_HANDLE hCipher, CVI_SIZE_T szSrcAddr, CVI_SIZE_T szDestAddr,
			       CVI_U32 u32ByteLength);

CVI_S32 CVI_UNF_CIPHER_EncryptVir(CVI_CIPHER_HANDLE hCipher, const CVI_U8 *pu8SrcData, CVI_U8 *pu8DestData,
				  CVI_U32 u32ByteLength);

CVI_S32 CVI_UNF_CIPHER_DecryptVir(CVI_CIPHER_HANDLE hCipher, const CVI_U8 *pu8SrcData, CVI_U8 *pu8DestData,
				  CVI_U32 u32ByteLength);

CVI_S32 CVI_UNF_CIPHER_EncryptMulti(CVI_CIPHER_HANDLE hCipher, const CVI_UNF_CIPHER_DATA_S *pstDataPkg,
				    CVI_U32 u32DataPkgNum);

CVI_S32 CVI_UNF_CIPHER_GetHandleConfig(CVI_CIPHER_HANDLE hCipher, CVI_UNF_CIPHER_CTRL_S *pstCtrl);

CVI_S32 CVI_UNF_CIPHER_DecryptMulti(CVI_CIPHER_HANDLE hCipher, const CVI_UNF_CIPHER_DATA_S *pstDataPkg,
				    CVI_U32 u32DataPkgNum);

CVI_S32 CVI_UNF_CIPHER_GetTag(CVI_CIPHER_HANDLE hCipher, CVI_U8 *pu8Tag, CVI_U32 *pu32TagLen);

CVI_S32 CVI_UNF_CIPHER_GetRandomNumber(CVI_U32 *pu32RandomNumber);

CVI_S32 CVI_UNF_CIPHER_HashInit(const CVI_UNF_CIPHER_HASH_ATTS_S *pstHashAttr, CVI_CIPHER_HANDLE *pHashHandle);

CVI_S32 CVI_UNF_CIPHER_HashUpdate(CVI_CIPHER_HANDLE hHashHandle, const CVI_U8 *pu8InputData, CVI_U32 u32InputDataLen);

CVI_S32 CVI_UNF_CIPHER_HashFinal(CVI_CIPHER_HANDLE hHashHandle, CVI_U8 *pu8OutputHash);

CVI_S32 CVI_UNF_CIPHER_RsaPublicEncrypt(const CVI_UNF_CIPHER_RSA_PUB_ENC_S *pstRsaEnc, const CVI_U8 *pu8Input,
					CVI_U32 u32InLen, CVI_U8 *pu8Output, CVI_U32 *pu32OutLen);

CVI_S32 CVI_UNF_CIPHER_RsaPrivateDecrypt(const CVI_UNF_CIPHER_RSA_PRI_ENC_S *pstRsaDec, const CVI_U8 *pu8Input,
					 CVI_U32 u32InLen, CVI_U8 *pu8Output, CVI_U32 *pu32OutLen);

CVI_S32 CVI_UNF_CIPHER_RsaPrivateEncrypt(const CVI_UNF_CIPHER_RSA_PRI_ENC_S *pstRsaEnc, const CVI_U8 *pu8Input,
					 CVI_U32 u32InLen, CVI_U8 *pu8Output, CVI_U32 *pu32OutLen);

CVI_S32 CVI_UNF_CIPHER_RsaPublicDecrypt(const CVI_UNF_CIPHER_RSA_PUB_ENC_S *pstRsaDec, const CVI_U8 *pu8Input,
					CVI_U32 u32InLen, CVI_U8 *pu8Output, CVI_U32 *pu32OutLen);

CVI_S32 CVI_UNF_CIPHER_RsaSign(const CVI_UNF_CIPHER_RSA_SIGN_S *pstRsaSign, const CVI_U8 *pu8InData,
			       CVI_U32 u32InDataLen, const CVI_U8 *pu8HashData, CVI_U8 *pu8OutSign,
			       CVI_U32 *pu32OutSignLen);

CVI_S32 CVI_UNF_CIPHER_RsaVerify(const CVI_UNF_CIPHER_RSA_VERIFY_S *pstRsaVerify, const CVI_U8 *pu8InData,
				 CVI_U32 u32InDataLen, const CVI_U8 *pu8HashData, const CVI_U8 *pu8InSign,
				 CVI_U32 u32InSignLen);


#endif /* end of include guard: CVI_UNF_CIPHER_H_FYUVBDPZ */
